/**
 * &copy; 2008 dataSentinel (http://www.datasentinel.com)
 * All Rights Reserved.
 */
package com.datasentinel.rooms.util.sh3d;

import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import java.util.Iterator;

import com.eteks.sweethome3d.model.Camera;
import com.eteks.sweethome3d.model.HomePieceOfFurniture;
import com.eteks.sweethome3d.model.Wall;

/**
 * @author Rick Power
 *
 */
public class CollisionUtils
{
	public static boolean testForIntersectionWithWallsOrPieces(Collection<Wall> walls, Collection<HomePieceOfFurniture> pieces, HomePieceOfFurniture homePiece)
	{
		Rectangle2D pieceRect = new Rectangle2D.Float(homePiece.getX()-homePiece.getWidth()/2, homePiece.getY()-homePiece.getDepth()/2, homePiece.getWidth(), homePiece.getDepth());
	    return testForIntersectionWithWalls(walls,pieceRect) || null != testForIntersectionWithPieces(pieces,pieceRect,homePiece);
	}
	
	public static boolean testForIntersectionWithWalls(Collection<Wall> walls, HomePieceOfFurniture homePiece)
	{
		Rectangle2D pieceRect = new Rectangle2D.Float(homePiece.getX()-homePiece.getWidth()/2, homePiece.getY()-homePiece.getDepth()/2, homePiece.getWidth(), homePiece.getDepth());
		return testForIntersectionWithWalls(walls, pieceRect);
	}
	
	public static boolean testForIntersectionWithWalls(Collection<Wall> walls, Camera camera)
	{
		Rectangle2D cameraRect = new Rectangle2D.Float(camera.getX()-10, camera.getY()-10, 20, 20);
		return testForIntersectionWithWalls(walls, cameraRect);
	}
	
	public static HomePieceOfFurniture testForIntersectionWithPieces(Collection<HomePieceOfFurniture> pieces,Camera camera)
	{
		Rectangle2D cameraRect = new Rectangle2D.Float(camera.getX()-10, camera.getY()-10, 20, 20);
		return testForIntersectionWithPieces(pieces, cameraRect, null);
	}
	
	private static HomePieceOfFurniture testForIntersectionWithPieces(Collection<HomePieceOfFurniture> pieces, Rectangle2D rectangle, HomePieceOfFurniture ignore)
	{
		for (HomePieceOfFurniture piece : pieces)
		{
			if(piece.equals(ignore)) continue;
			Shape pieceShape = getShape(piece.getPoints());
			if(pieceShape.intersects(rectangle))
				return piece;
		}
		return null;
	}
	
	public static Iterator<HomePieceOfFurniture> testForIntersectionWithPieces(final Collection<HomePieceOfFurniture> pieces, final HomePieceOfFurniture ignore)
	{
		return new Iterator<HomePieceOfFurniture>(){
			private Iterator<HomePieceOfFurniture> i = pieces.iterator();
			private Rectangle2D pieceRect = new Rectangle2D.Float(ignore.getX()-ignore.getWidth()/2, ignore.getY()-ignore.getDepth()/2, ignore.getWidth(), ignore.getDepth());
			private HomePieceOfFurniture next = nextPiece();
			private HomePieceOfFurniture nextPiece()
			{
				while (i.hasNext())
				{
					next = i.next();
					if (next.equals(ignore))
						continue;
					Shape pieceShape = getShape(next.getPoints());
					if (pieceShape.intersects(pieceRect))
						return next;
				}
				return null;
			}
			@Override
			public boolean hasNext()
			{
				return next != null;
			}
			@Override
			public HomePieceOfFurniture next()
			{
				HomePieceOfFurniture result = next;
				next = nextPiece();
				return result;
			}
			@Override
			public void remove()
			{
			}};
		}
	
	private static boolean testForIntersectionWithWalls(Collection<Wall> walls,Rectangle2D rectangle)
	{
		for (Wall wall : walls)
		{
			Shape wallShape = getShape(wall.getPoints());
			if(wallShape.intersects(rectangle))
				return true;
		}
		return false;
	}
	
	private static Shape getShape(float [][] points)
	{
	    GeneralPath path = new GeneralPath();
	    path.moveTo(points [0][0], points [0][1]);
	    for (int i = 1; i < points.length; i++) {
	    	path.lineTo(points [i][0], points [i][1]);
	    }
	    path.closePath();
	    return path;
	 }
}
